import psutil
import time
import subprocess
import logging
from selenium import webdriver
from selenium.common.exceptions import WebDriverException
from config.settings import get_config
from selenium.webdriver.chrome.service import Service

class BrowserManagerError(Exception):
    """自定义浏览器管理异常"""
    pass


class BrowserManager:
    _MAX_RETRIES = 3
    _RETRY_DELAY = 2
    _BROWSER_TIMEOUT = 5  # 浏览器启动超时时间（秒）

    @classmethod
    def _validate_driver(cls, driver):
        """验证浏览器实例有效性"""
        try:
            # 通过获取当前URL验证实例状态
            current_url = driver.current_url
            print(f"浏览器实例验证通过，当前URL: {current_url}")
            return True
        except WebDriverException as e:
            print(f"浏览器实例验证失败: {str(e)}")
            return False

    @classmethod
    def _force_cleanup(cls, browser_name="chrome"):
        """强制终止残留浏览器进程"""
        try:
            # 终止浏览器进程
            for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
                try:
                    process_info = proc.as_dict(attrs=['pid', 'name', 'cmdline'])
                    if any([
                        browser_name.lower() in (process_info['name'] or '').lower(),
                        'chromedriver' in (process_info['name'] or '').lower(),
                        any('--test-type=webdriver' in cmd for cmd in (process_info['cmdline'] or []))
                    ]):
                        proc.kill()
                except (psutil.NoSuchProcess, psutil.AccessDenied):
                    continue

            # 强制清理Linux系统残留
            if psutil.LINUX:
                subprocess.run(["pkill", "-9", "-f", "chrome"], check=False)
                subprocess.run(["pkill", "-9", "-f", "chromedriver"], check=False)

        except Exception as e:
            logging.error(f"进程清理异常: {str(e)}")

    @classmethod
    def _create_chrome_driver(cls, config):
        """创建Chrome浏览器实例"""
        options = webdriver.ChromeOptions()

        # 基础配置
        options.binary_location = config.chrome_binary_path
        # 浏览器最大化
        options.add_argument('--start-maximized')
        # 浏览器忽略安全连接
        options.add_argument('--ignore-certificate-errors')
        options.add_argument('--no-sandbox')
        options.add_argument('--disable-dev-shm-usage')
        options.add_argument('--disable-gpu')
        options.add_argument('--disable-software-rasterizer')

        # 无头模式配置
        if config.headless == "True":
            options.add_argument("--headless=new")
            options.add_argument("--disable-extensions")
            options.add_argument("--remote-debugging-port=9222")

        # 下载配置
        prefs = {
            "download.default_directory": config.download_dir,
            "download.prompt_for_download": False,
            "safebrowsing.enabled": True,
            "credentials_enable_service": False,
            "profile.password_manager_enabled": False
        }
        options.add_experimental_option("prefs", prefs)

        # 创建服务实例
        service = Service(
            executable_path=config.chrome_driver_path,
            service_args=['--verbose']
        )

        try:
            driver = webdriver.Chrome(
                service=service,
                options=options,
                keep_alive=False  # 禁用长连接
            )

            # 设置命令超时
            driver.command_executor.set_timeout(cls._BROWSER_TIMEOUT)

            # 执行验证操作
            driver.get("about:blank")
            if not cls._validate_driver(driver):
                raise BrowserManagerError("浏览器实例验证失败")

            return driver
        except WebDriverException as e:
            cls._force_cleanup()
            raise BrowserManagerError(f"浏览器创建失败: {str(e)}")

    @classmethod
    def _create_firefox_driver(cls, config):
        """创建Firefox浏览器实例（示例）"""
        # 实现类似Chrome的清理逻辑
        raise NotImplementedError("Firefox驱动暂未实现")

    @classmethod
    def get_driver(cls, device_type=None):
        """获取浏览器驱动（自动恢复版）"""
        config = get_config(device_type)

        for attempt in range(1, cls._MAX_RETRIES + 1):
            try:
                logging.info(f"尝试启动浏览器（第{attempt}次）")

                # 创建前清理
                if attempt > 1:
                    cls._force_cleanup()
                    time.sleep(cls._RETRY_DELAY * attempt)  # 递增等待

                # 创建浏览器实例
                if config.browser_name.lower() == "chrome":
                    driver = cls._create_chrome_driver(config)
                elif config.browser_name.lower() == "firefox":
                    driver = cls._create_firefox_driver(config)
                else:
                    raise BrowserManagerError(f"不支持的浏览器: {config.browser_name}")

                # 配置通用参数
                driver.implicitly_wait(config.implicit_wait)
                driver.set_page_load_timeout(config.implicit_wait)

                logging.info("浏览器实例创建成功")
                return driver

            except Exception as e:
                logging.info(f"第{attempt}次尝试失败: {str(e)}")
                if attempt == cls._MAX_RETRIES:
                    logging.critical("达到最大重试次数，终止流程")
                    raise BrowserManagerError(f"无法启动浏览器: {str(e)}") from e

    @classmethod
    def setup_driver(cls, device_type=None):
        """兼容旧接口"""
        return cls.get_driver(device_type)